/*
有 N种物品和一个容量是 V的背包。
第i种物品最多有si件，每件体积是vi，价值是 wi。
求解将哪些物品装入背包，可使物品体积总和不超过背包容量，且价值总和最大。
输出最大价值。
输入格式
第一行两个整数，N，V(0<N≤1000, 0<V≤20000)
，用空格隔开，分别表示物品种数和背包容积。
接下来有 N行，每行三个整数 vi,wi,si，用空格隔开，分别表示第i种物品的体积、价值和数量。
输出格式
输出一个整数，表示最大价值。
*/
#include<bits/stdc++.h>
#define endl "\n"
#define ll long long
#define all(rq) rq.begin(),rq.end()
#define max(a,b) (a<b?b:a)
#define min(a,b) (a<b?a:b)

using namespace std;
const int INF=0x3f3f3f3f;

int main(){
	int n,m;
	cin>>n>>m;
	
	vector<int> v(n+1),w(n+1),s(n+1);
	for(int i=1;i<=n;i++){
		cin>>v[i]>>w[i]>>s[i];
	}
	
	vector<int> f(m+1);
	
	vector<int> q(m+1);
	for(int i=1;i<=n;i++){
		
		for(int r=0;r<v[i];r++){
			int hh=0,tt=-1;
			
			vector<int> g=f;
			for(int j=r;j<=m;j+=v[i]){
				
				while(hh<=tt && j-q[hh]>s[i]*v[i]){ //先将队头过期容量弹出 即当前容量j与队头的容量的差值大于 si*vi 
					hh++;
				}
				
				while(hh<=tt && g[q[tt]]+(j-q[tt])/v[i]*w[i]<=g[j]){ //将队尾无用元素弹出维持单调队列单调递减特性 
					tt--;
				}
				
				q[++tt]=j; //将当前容量加入队尾 
				
				f[j]=g[q[hh]]+(j-q[hh])/v[i]*w[i]; //队头容量即为能得到最大价值容量
			}
		}
	}
	
	
	cout<<f[m]<<endl; 
	return 0;
}